package com.sacker.work.analyze.dict.multiChrome;

import java.util.concurrent.SynchronousQueue;

/**
 * Created by asus on 2018/6/19.
 */
public class MyAssigner {
    private Thread[] ThreadChi;
    private final SynchronousQueue<Node> blockingDeque = new SynchronousQueue<>();
    private final Tick tick = new Tick();
    private int maxNodeNumber = 0;

    private boolean isAllFinish() {
        return maxNodeNumber == tick.sum;
    }

    private boolean iswaitForFinish = false;

    public void waitForFinish() {
        iswaitForFinish = true;
        try {
            synchronized (this) {
                while (!isAllFinish()) {
                    System.out.println("in : " + Thread.currentThread().getName());
                    this.wait();
                }
            }
        } catch (InterruptedException e) {
        }
        iswaitForFinish = false;
    }

    public void addNode(Node node) {
        maxNodeNumber++;
        try {
            blockingDeque.put(node);
        } catch (InterruptedException e) {
        }
    }

    public void run(Node node) {
        node.run();
    }

    /**
     * 任务分配者，Node为最小任务
     * 请使用静态全局变量，不要作为局部变量，否则线程数量会爆炸
     * 其次，加完 node 记得调用 waitForFinish等待线程完成
     */
    public MyAssigner(int n) {
        ThreadChi = new Thread[n];
        final MyAssigner thisMyAssigner = this;
        for (int i = 0; i < ThreadChi.length; i++) {
            ThreadChi[i] = new Thread(() -> {
                for (; ; ) {
                    try {
                        if (Thread.currentThread().isInterrupted()) break;
                        Node node = blockingDeque.take();
                        run(node);
                        tick.add();

                        if (iswaitForFinish && blockingDeque.isEmpty()) {
                            System.out.println(Thread.currentThread().getName() + ":close");
                            Thread.currentThread().interrupt();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName() + ":interrupt");
            });
            ThreadChi[i].start();
        }
    }

    static class Tick {
        int sum = 0;

        public void add() {
            synchronized (this) {
                sum++;
            }
        }
    }
}
